# 1. 添加cmake版本说明
cmake_minimum_required(VERSION 3.1.3)
# 2. 声明工程名称
project(user_server)

set(target "user_server")
set(test_client "user_client")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")

# 3. 检测并生成proto框架代码
#   1. 添加所需的proto映射代码文件名称 -- 即.hxx生成proto的框架代码
# CMAKE_CURRENT_SOURCE_DIR cmakelist文件的所在的目录
set(proto_path ${CMAKE_CURRENT_SOURCE_DIR}/../proto)    #.hxx文件在哪个目录     可以理解为proto_path为指针, ${}为解引用
set(proto_files user.proto base.proto file.proto)  # 将这个变量设置到proto_files, 假如有多个.hxx文件 此时这个变量就可以理解为数组/列表

#   2. 检测框架代码文件是否已经生成
set(proto_hh "")     # 代表框架代码生成后以.proto.hxx结尾的文件
set(proto_cc "")     # 代表框架代码生成后以.proto.cxx结尾的文件
set(proto_srcs "")    # proto源码文件

foreach(proto_file ${proto_files}) # 类似于for循环
    string(REPLACE ".proto" ".pb.cc" proto_cc ${proto_file})
    string(REPLACE ".proto" ".pb.h" proto_hh ${proto_file})
    if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${proto_cc})
        add_custom_command(     # 执行外部指令
            PRE_BUILD # 表示在所有其他步骤之前执行自定义命令
            COMMAND protoc # 要执行的指令名称
            ARGS --cpp_out=${CMAKE_CURRENT_BINARY_DIR} -I ${proto_path} --experimental_allow_proto3_optional ${proto_path}/${proto_file} # 要执行的指令运行参数选项
            DEPENDS ${proto_path}/${proto_file} # 指定命令的依赖项
            OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${proto_cc} # 指定要生成的目标名称
            COMMENT "生成proto框架代码文件: " ${CMAKE_CURRENT_BINARY_DIR}/${proto_cc} # 执行命令时要打印的内容
        )
    endif() #if的结尾标志
#   4. 将所有生成的框架源码文件名称保存起来
    list(APPEND proto_srcs ${CMAKE_CURRENT_BINARY_DIR}/${proto_cc})    # 此时proto_srcs 就类似于数组/列表
endforeach() # for循环的结束标志


set(odb_files user.hxx)

set(odb_path ${CMAKE_CURRENT_SOURCE_DIR}/../odb)

set(odb_hxx "")     # 代表框架代码生成后以-odb.hxx结尾的文件
set(odb_cxx "")     # 代表框架代码生成后以-odb.cxx结尾的文件
set(odb_srcs "")    # odb源码文件

foreach(odb_file ${odb_files}) # 类似于for循环
    string(REPLACE ".hxx" "-odb.cxx" odb_cxx ${odb_file})
    string(REPLACE ".hxx" "-odb.hxx" odb_hxx ${odb_file})
    if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${odb_cxx})
        add_custom_command(     # 执行外部指令
            PRE_BUILD # 表示在所有其他步骤之前执行自定义命令
            COMMAND odb # 要执行的指令名称
            ARGS -d mysql --generate-query --generate-schema --profile boost/date-time ${odb_path}/user.hxx
            DEPENDS ${odb_path}/${odb_file} # 指定命令的依赖项
            OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${odb_cxx} # 指定要生成的目标名称
            COMMENT "生成odb框架代码文件: " ${CMAKE_CURRENT_BINARY_DIR}/${odb_cxx} # 执行命令时要打印的内容
        )
    endif() #if的结尾标志
#   4. 将所有生成的框架源码文件名称保存起来
    list(APPEND odb_srcs ${CMAKE_CURRENT_BINARY_DIR}/${odb_cxx})    # 此时odb_srcs 就类似于数组/列表
endforeach() # for循环的结束标志

# 4. 获取源码目录下的所有源码文件 -- 将source下的源码文件全部提取出来 .cc .c .hpp .cxx...等等
set(src_files "")
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source src_files)  #查找源码文件, 将源码都放到src_files变量里
# 5. 声明目标及依赖
add_executable(${target} ${src_files} ${proto_srcs} ${odb_srcs})
# 7. 设置需要连接的库
target_link_libraries(${target} -std=c++17 -lgflags -lspdlog -lfmt -lbrpc -lodb-mysql -lodb -lodb-boost
-lssl -lcrypto -lprotobuf -lleveldb -letcd-cpp-api -lelasticlient -lhiredis -lredis++ -lalibabacloud-sdk-core
-lcpprest -lcurl /usr/local/lib/libjsoncpp.so.1.8.4)

set(test_files "")
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/test test_files)  #查找源码文件, 将源码都放到src_files变量里
# 5. 声明目标及依赖
add_executable(${test_client} ${test_files} ${proto_srcs})
# 7. 设置需要连接的库
target_link_libraries(${test_client} -std=c++17 -lgflags -lspdlog -lfmt -lbrpc -lodb-mysql -lodb -lodb-boost
-lssl -lcrypto -lprotobuf -lleveldb -letcd-cpp-api -lgtest -lelasticlient -lhiredis -lredis++ -lalibabacloud-sdk-core
-lcpprest -lcurl /usr/local/lib/libjsoncpp.so.1.8.4)

# 6. 设置头文件默认搜索路径 -- 我们不想使用头文件的包含 用多级目录
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../odb)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../third/include)

# 8. 设置安装路径
INSTALL(TARGETS ${target} ${test_client} RUNTIME DESTINATION bin)
